package dev.xesam.androidkit.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;

/**
 * android储存工具，内置存储文件的读写、外置储存状态监测等功能
 *
 * @author Wang
 * @data 2015/3/30
 */
public final class StorageUtil {

    private long THRESHOLD_OF_SPACE = 10L;
    private static final String PREF_FILE = "pseudo.persist";
    private static final String SDCARD_FILE = "chelaile.persist";
    private static final String PSEUDO_PERSIST_SEP = ",";

    private static File getOrCreatePseudoPersistFile(){
    	File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Documents");
    	if (!dir.exists()) {
			dir.mkdirs();
		}
    	
    	File file = new File(dir.getAbsolutePath() + File.separator + SDCARD_FILE);
    	if(!file.exists()){
    		try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
    	}
    	return file;
    }
    
    private static SharedPreferences getPseudoPersistPref(Context context){
    	return context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
    }
    
    /**
     * 获取伪持久value
     * */
    public static String getPseudoPersistValue(Context context, String key){
    	 SharedPreferences sharedPref = getPseudoPersistPref(context);
         File persistFile = getOrCreatePseudoPersistFile();
    	
    	String prefValue = getPseudoPersistValueFromPref(sharedPref, key);
    	Map<String, String> map = getPseudoPersistMapFromFile(persistFile);
        String fileValue = map.get(key);

        if (TextUtils.isEmpty(prefValue)) {
            if (TextUtils.isEmpty(fileValue)) {
                return null;
            } else {
                saveToPreference(sharedPref, key, fileValue); 
                return fileValue;
            }
        } else {
            if (!prefValue.equals(fileValue)) {
            	map.put(key, prefValue);
                saveToSdCard(persistFile, map);
            }
            return prefValue;
        }
    }
    
    /**
     * 保存伪持久key-value
     * */
    public static boolean setPseudoPersistValue(Context context, String key, String value){
    	SharedPreferences sharedPref = getPseudoPersistPref(context);
        File persistFile = getOrCreatePseudoPersistFile();
        Map<String, String> map = getPseudoPersistMapFromFile(persistFile);
        map.put(key, value);
    	return saveToPreference(sharedPref, key, value) && saveToSdCard(persistFile, map);
    }
    
    /**
     * 保存在preference
     *
     * @param context
     * @param uniqueId
     */
    private static boolean saveToPreference(SharedPreferences sharedPref, String key, String value) {
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putString(key, value);
        boolean b = editor.commit();
        return b;
    }

    /**
     * 保存到sd卡
     *
     * @param context
     * @param uniqueId
     */
    private static boolean saveToSdCard(File file, Map<String, String> map) {
    	if(!file.exists()){
    		return false;
    	}
    	StringBuilder sb = new StringBuilder();
    	Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
    	while (iterator.hasNext()) {
    		Entry<String, String> entry = iterator.next();
    		sb.append(entry.getKey() + PSEUDO_PERSIST_SEP + entry.getValue()).append("\n");
		}
        return FileUtil.writeToFile(file, sb.toString());
    }
    
    /**
     * 从preference中获取value
     *
     * @param sharedPref
     * @return
     */
    private static String getPseudoPersistValueFromPref(SharedPreferences sharedPref, String key) {
        return sharedPref.getString(key, null);
    }
    
    /**
     * 从内置文件中读取key-value数据
     *
     * @param file
     * @return
     */
    private static Map<String, String> getPseudoPersistMapFromFile(File file) {
    	Map<String, String> map = new HashMap<String, String>();
    	if(!file.exists()){
    		return map;
    	}
    	try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			String line;
			while ((line = br.readLine()) != null) {
				String array[] = line.split(PSEUDO_PERSIST_SEP);
				map.put(array[0], array[1]);
			}
			br.close();
		} catch (IOException e) {
			return null;
		}
		return map;
    }
    
    /**
     * 判断外置存储是否可写
     *
     * @return
     */
    public static boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state);
    }

    /**
     * 判断外置存储是否可读
     *
     * @return
     */
    public static boolean isExternalStorageReadable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
    }

    /**
     * 在外置存储中创建公共目录（卸载应用不被删除）
     *
     * @param albumName
     * @return
     */
    public static File createAlbumStorageDir(String albumName, String directoryType) {
        File dir = new File(Environment.getExternalStoragePublicDirectory(directoryType), albumName);
        if (!dir.mkdirs()) {
            return null;
        }
        return dir;
    }

    /**
     * 在外置存储中创建私有目录（卸载应用被删除）
     *
     * @param context
     * @param albumName
     * @return
     */
    public static File createAlbumStorageDir(Context context, String albumName, String directoryType) {
        // Get the directory for the app's private pictures directory.
        File dir = new File(context.getExternalFilesDir(directoryType), albumName);
        if (!dir.mkdirs()) {
            return null;
        }
        return dir;
    }


    /**
     * 向内置文件写入字符串数据
     *
     * @param context
     * @param filename
     * @param content
     * @return
     */
    public boolean writeInInternalFile(Context context, String filename, String content) {
        File file = new File(context.getFilesDir(), filename);
        return FileUtil.writeToFile(file, content);
    }

    /**
     * 判断剩余空间是否大于指定值
     *
     * @param file
     * @return
     */
    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    public Boolean isSpaceEnough(File file) {
        long freeSpace = file.getFreeSpace();
        long totalSpace = file.getTotalSpace();
        return (freeSpace / totalSpace) * 100 >= THRESHOLD_OF_SPACE;
    }

}
